runtime,cl: Go-style panic tracebacks and exact log/slog/testing locations, with gc-verified acceptance suite#2023
Closed
cpunion wants to merge 60 commits into
Closed
runtime,cl: Go-style panic tracebacks and exact log/slog/testing locations, with gc-verified acceptance suite#2023cpunion wants to merge 60 commits into
cpunion wants to merge 60 commits into
Conversation
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
cpunion
force-pushed
the
codex/stage5-acceptance
branch
2 times, most recently
from
July 4, 2026 03:36
ab82a5d to
b8f8ff3
Compare
This was referenced Jul 4, 2026
cpunion
force-pushed
the
codex/stage5-acceptance
branch
4 times, most recently
from
July 4, 2026 04:58
e6a4518 to
5d7c3f0
Compare
cpunion
force-pushed
the
codex/stage5-acceptance
branch
from
July 4, 2026 06:12
5d7c3f0 to
5e895e7
Compare
This was referenced Jul 4, 2026
Merged
cpunion
added a commit
to cpunion/llgo
that referenced
this pull request
Jul 6, 2026
…l, 75m job) The macos coverage job's test step already ran at ~44-45m on the xgo-dev#2023 base (job wall 50:56); the recover-ownership tests push it past the 45m internal go-test alarm — killed at 45m with ~10 minutes of suites left. Not a performance regression: local full ssa+cl on the same tree run in ~10 minutes; the mac CI runner is ~5x slower on llgo-building tests.
This was referenced Jul 6, 2026
A fabricated Mach-O (segments, sections, symtab, chained-fixup imports and an empty page chain) drives load, bind-target resolution, record decoding and both Rewrite outcomes (in-place and stub-section spill) end to end. codesign now runs only when the input carries LC_CODE_SIGNATURE: real lld executables always do, unsigned inputs need no signature and codesign rejects them. Also cover asmQuoteELFSymbol, the empty-table initializers and the Rewrite error paths. Package coverage: pclnpost 69% -> 86%. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Every Go function on supported targets keeps the frame-pointer chain
("frame-pointer"="non-leaf", gated by Program.NeedsFramePointer to
linux/darwin — on embedded targets the unwinder does not exist and the
layout change perturbed the conservative GC on ESP32-C3). runtime.Caller,
Callers, CallersFrames, Stack and the unrecovered-panic dump walk
[fp]/[fp+w] directly and symbolize through the prebuilt ftab and pcline
tables:
- Return addresses resolve at pc-1 (Go's convention); statement labels
can land exactly on a return address, so raw-pc nearest-below reported
the following line. The convention holds with or without the prebuilt
table (text bounds fall back to the first-use frame table — link-phase
overflow layouts otherwise silently disabled it, the root cause of the
amd64 CI failures).
- The walk is bounded to the program's own text: libc frames without FP
discipline decode as wild pcs that nearest-below would attribute to
arbitrary functions.
- Methods and anonymous functions are now trackable (methods had no
pcline labels; closures lost their innermost frame to tail-call
optimization), and mid-function aligned pcs merge statement records
instead of returning declaration lines.
- frameSymbol results are memoized per pc (deep re-walks paid a dladdr
per frame: 32-frame walks 8µs -> 180ns) and the pcline table is built
during the startup pre-warm (lazily building it inside the first
Caller cost ~200µs at scale).
- Shadow-stack instrumentation is no longer emitted; LLGO_SHADOW_STACK=1
keeps the legacy emitters for one release. Tracked functions retain
noinline, no-tail-call and the data-only pcline records.
- libunwind is gone: the clite stacktrace fallback walks the FP chain
with dladdr names (same output format), and linux binaries no longer
link -lunwind.
Semantics are gc ground truth, verified against go: physical stacks show
every real frame; interface-chain Caller marks land at skip 3 and
closure chains at skip 4 (the old expectations encoded shadow-stack
frame loss). Perf (best-of, mac/linux): hot.Caller0 17/37ns (Go
155/241), deep.Direct512 2.8µs (Go 9.7µs; was 87-95µs), bigfunc.Work
18µs (Go 30µs; was 433µs), binary size unchanged or smaller.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
IR goldens gain the frame-pointer attribute (out.ll files carry no attribute groups and needed no regeneration); the legacy shadow-stack emitter assertions opt into LLGO_SHADOW_STACK; statement-line probes move to gc ground-truth skip counts; NeedsFramePointer target matrix and pclnpost symbolAddr/decodePtr edges covered. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ct log/slog/testing locations An unrecovered panic now prints a Go-style traceback (function names plus file:line per physical frame) through a PanicTraceback hook the public runtime registers; the clite dladdr dump remains the fallback when the FP walk or the tables are unavailable. Caller-frame tracking now applies uniformly: the blanket stdlib exclusion is gone, so the same per-package reaches-runtime.Caller analysis that already covered third-party code tracks log.Output, slog's Logger.log and testing's decorate chains (their thin wrappers were inlined, making fixed Caller depths count past them — log.Lshortfile printed "???:1"). Call sites into caller-pc-consuming functions of other packages get a statement anchor so the attributed frame reports the exact line. The collector also picks up named-type methods declared by the package itself — a type used only concretely never enters RuntimeTypes, which is exactly how slog.(*Logger).Info escaped tracking. hello-world size cost: +368 bytes (the traceback printer). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Four scenarios, every expectation verified against gc: unrecovered panic tracebacks; log.Lshortfile and slog AddSource (text+JSON, package funcs and logger methods); a failing t.Errorf under llgo test; and an introspection grab-bag (goroutine/init/defer callers, FuncForPC names for methods, closures and generics, the errors-with-stack capture idiom). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
cpunion
force-pushed
the
codex/stage5-acceptance
branch
from
July 8, 2026 05:26
a5fa2fc to
37c127c
Compare
cpunion
added a commit
to cpunion/llgo
that referenced
this pull request
Jul 8, 2026
…upport Re-expresses the surviving value of xgo-dev#1892 on the xgo-dev#2023 base (its other ~10k lines were an earlier draft of the funcinfo/pclntab machinery, since superseded by xgo-dev#2012/xgo-dev#2016/xgo-dev#2019): - //go:nointerface methods no longer satisfy interfaces: the pragma is recorded at import (cl/import.go -> Program.SetNoInterfaceMethod) and filtered out of abi uncommon method tables; GlobalDCE metadata takes the filtered selection list. Retires the typeparam/mdempsky/15 goroot xfails (validated go1.26 darwin, ci directive mode). - Type-assertion failure between same-named types from different scopes appends '(types from different scopes)' (gc wording). - MatchesClosure unwraps closure types on both sides, fixing assertions between closure and plain function types. - reflect.(*rtype).Method builds the method func value with the closure layout allocation (fixes reflect method-value identity). - xfail: retire fixedbugs/issue16130, fixedbugs/issue29735 (validated go1.24 + go1.26 darwin), and reword typeparam/mdempsky/16 - the panic value now implements runtime.Error; the message still lacks the source interface type and prints the command-line-arguments package path.
cpunion
added a commit
to cpunion/llgo
that referenced
this pull request
Jul 8, 2026
Re-expresses xgo-dev#1918 on the xgo-dev#2023 base (its remaining ~11k diff lines were the pre-xgo-dev#2012 funcinfo draft, superseded by the stage-5 chain): - recover() only succeeds when called directly by a deferred function (gc semantics): the panic node records the owning Defer frame at rethrow (panicKey/panicNode + GoDeferData), and Recover checks the caller is that frame's direct deferred call. Closure wraps carry StartRecoverFrameAlias/EndRecoverFrame so method-value and closure adapters stay transparent to the ownership check. - Rethrow keeps the xgo-dev#2023 PanicTraceback hook on the unrecovered path. - xfail: retire fixedbugs/issue4066 (2m-timeout entries; now runs in ~2.7s), fixedbugs/issue73916 and issue73916b (go1.26 recover semantics), validated on darwin/arm64 go1.26. Supersedes xgo-dev#1918.
cpunion
added a commit
to cpunion/llgo
that referenced
this pull request
Jul 8, 2026
Re-expresses xgo-dev#1906 on the xgo-dev#2023 base (its remaining ~11k diff lines were the pre-xgo-dev#2012 funcinfo draft, superseded by the stage-5 chain): - cl gains a liveness analysis for stack-allocated objects: allocas whose last use has passed are cleared so bdwgc's conservative stack scan stops keeping dead stack objects (and what they point to) alive; pointer registers are clobbered around the trigger points (llgo_clobber_pointer_regs) and dead stack slots holding the target are zeroed (llgo_clear_stack_ptr, pthread stack-bounds walk). - runtime.SetFinalizer paths (mfinal, runtime_gc, bdwgc binding) hook the cleared-slot machinery so finalizers for dead stack objects run. - xfail: retire deferfin.go, stackobj.go, stackobj3.go, validated on darwin/arm64 go1.24 + go1.26 (stackobj2 already passed). Carries the xgo-dev#2035 shared-GOCACHE commit temporarily (same patch-id, auto-dedups when the chain rebases after xgo-dev#2035 merges). Supersedes xgo-dev#1906.
Collaborator
Author
cpunion
added a commit
to cpunion/llgo
that referenced
this pull request
Jul 8, 2026
…upport Re-expresses the surviving value of xgo-dev#1892 on the xgo-dev#2023 base (its other ~10k lines were an earlier draft of the funcinfo/pclntab machinery, since superseded by xgo-dev#2012/xgo-dev#2016/xgo-dev#2019): - //go:nointerface methods no longer satisfy interfaces: the pragma is recorded at import (cl/import.go -> Program.SetNoInterfaceMethod) and filtered out of abi uncommon method tables; GlobalDCE metadata takes the filtered selection list. Retires the typeparam/mdempsky/15 goroot xfails (validated go1.26 darwin, ci directive mode). - Type-assertion failure between same-named types from different scopes appends '(types from different scopes)' (gc wording). - MatchesClosure unwraps closure types on both sides, fixing assertions between closure and plain function types. - reflect.(*rtype).Method builds the method func value with the closure layout allocation (fixes reflect method-value identity). - xfail: retire fixedbugs/issue16130, fixedbugs/issue29735 (validated go1.24 + go1.26 darwin), and reword typeparam/mdempsky/16 - the panic value now implements runtime.Error; the message still lacks the source interface type and prints the command-line-arguments package path.
cpunion
added a commit
to cpunion/llgo
that referenced
this pull request
Jul 8, 2026
Re-expresses xgo-dev#1918 on the xgo-dev#2023 base (its remaining ~11k diff lines were the pre-xgo-dev#2012 funcinfo draft, superseded by the stage-5 chain): - recover() only succeeds when called directly by a deferred function (gc semantics): the panic node records the owning Defer frame at rethrow (panicKey/panicNode + GoDeferData), and Recover checks the caller is that frame's direct deferred call. Closure wraps carry StartRecoverFrameAlias/EndRecoverFrame so method-value and closure adapters stay transparent to the ownership check. - Rethrow keeps the xgo-dev#2023 PanicTraceback hook on the unrecovered path. - xfail: retire fixedbugs/issue4066 (2m-timeout entries; now runs in ~2.7s), fixedbugs/issue73916 and issue73916b (go1.26 recover semantics), validated on darwin/arm64 go1.26. Supersedes xgo-dev#1918.
cpunion
added a commit
to cpunion/llgo
that referenced
this pull request
Jul 8, 2026
Re-expresses xgo-dev#1906 on the xgo-dev#2023 base (its remaining ~11k diff lines were the pre-xgo-dev#2012 funcinfo draft, superseded by the stage-5 chain): - cl gains a liveness analysis for stack-allocated objects: allocas whose last use has passed are cleared so bdwgc's conservative stack scan stops keeping dead stack objects (and what they point to) alive; pointer registers are clobbered around the trigger points (llgo_clobber_pointer_regs) and dead stack slots holding the target are zeroed (llgo_clear_stack_ptr, pthread stack-bounds walk). - runtime.SetFinalizer paths (mfinal, runtime_gc, bdwgc binding) hook the cleared-slot machinery so finalizers for dead stack objects run. - xfail: retire deferfin.go, stackobj.go, stackobj3.go, validated on darwin/arm64 go1.24 + go1.26 (stackobj2 already passed). Carries the xgo-dev#2035 shared-GOCACHE commit temporarily (same patch-id, auto-dedups when the chain rebases after xgo-dev#2035 merges). Supersedes xgo-dev#1906.
cpunion
added a commit
to cpunion/llgo
that referenced
this pull request
Jul 8, 2026
…upport Re-expresses the surviving value of xgo-dev#1892 on the xgo-dev#2023 base (its other ~10k lines were an earlier draft of the funcinfo/pclntab machinery, since superseded by xgo-dev#2012/xgo-dev#2016/xgo-dev#2019): - //go:nointerface methods no longer satisfy interfaces: the pragma is recorded at import (cl/import.go -> Program.SetNoInterfaceMethod) and filtered out of abi uncommon method tables; GlobalDCE metadata takes the filtered selection list. Retires the typeparam/mdempsky/15 goroot xfails (validated go1.26 darwin, ci directive mode). - Type-assertion failure between same-named types from different scopes appends '(types from different scopes)' (gc wording). - MatchesClosure unwraps closure types on both sides, fixing assertions between closure and plain function types. - reflect.(*rtype).Method builds the method func value with the closure layout allocation (fixes reflect method-value identity). - xfail: retire fixedbugs/issue16130, fixedbugs/issue29735 (validated go1.24 + go1.26 darwin), and reword typeparam/mdempsky/16 - the panic value now implements runtime.Error; the message still lacks the source interface type and prints the command-line-arguments package path.
cpunion
added a commit
to cpunion/llgo
that referenced
this pull request
Jul 8, 2026
Re-expresses xgo-dev#1918 on the xgo-dev#2023 base (its remaining ~11k diff lines were the pre-xgo-dev#2012 funcinfo draft, superseded by the stage-5 chain): - recover() only succeeds when called directly by a deferred function (gc semantics): the panic node records the owning Defer frame at rethrow (panicKey/panicNode + GoDeferData), and Recover checks the caller is that frame's direct deferred call. Closure wraps carry StartRecoverFrameAlias/EndRecoverFrame so method-value and closure adapters stay transparent to the ownership check. - Rethrow keeps the xgo-dev#2023 PanicTraceback hook on the unrecovered path. - xfail: retire fixedbugs/issue4066 (2m-timeout entries; now runs in ~2.7s), fixedbugs/issue73916 and issue73916b (go1.26 recover semantics), validated on darwin/arm64 go1.26. Supersedes xgo-dev#1918.
cpunion
added a commit
to cpunion/llgo
that referenced
this pull request
Jul 8, 2026
Re-expresses xgo-dev#1906 on the xgo-dev#2023 base (its remaining ~11k diff lines were the pre-xgo-dev#2012 funcinfo draft, superseded by the stage-5 chain): - cl gains a liveness analysis for stack-allocated objects: allocas whose last use has passed are cleared so bdwgc's conservative stack scan stops keeping dead stack objects (and what they point to) alive; pointer registers are clobbered around the trigger points (llgo_clobber_pointer_regs) and dead stack slots holding the target are zeroed (llgo_clear_stack_ptr, pthread stack-bounds walk). - runtime.SetFinalizer paths (mfinal, runtime_gc, bdwgc binding) hook the cleared-slot machinery so finalizers for dead stack objects run. - xfail: retire deferfin.go, stackobj.go, stackobj3.go, validated on darwin/arm64 go1.24 + go1.26 (stackobj2 already passed). Carries the xgo-dev#2035 shared-GOCACHE commit temporarily (same patch-id, auto-dedups when the chain rebases after xgo-dev#2035 merges). Supersedes xgo-dev#1906.
cpunion
added a commit
to cpunion/llgo
that referenced
this pull request
Jul 9, 2026
…upport Re-expresses the surviving value of xgo-dev#1892 on the xgo-dev#2023 base (its other ~10k lines were an earlier draft of the funcinfo/pclntab machinery, since superseded by xgo-dev#2012/xgo-dev#2016/xgo-dev#2019): - //go:nointerface methods no longer satisfy interfaces: the pragma is recorded at import (cl/import.go -> Program.SetNoInterfaceMethod) and filtered out of abi uncommon method tables; GlobalDCE metadata takes the filtered selection list. Retires the typeparam/mdempsky/15 goroot xfails (validated go1.26 darwin, ci directive mode). - Type-assertion failure between same-named types from different scopes appends '(types from different scopes)' (gc wording). - MatchesClosure unwraps closure types on both sides, fixing assertions between closure and plain function types. - reflect.(*rtype).Method builds the method func value with the closure layout allocation (fixes reflect method-value identity). - xfail: retire fixedbugs/issue16130, fixedbugs/issue29735 (validated go1.24 + go1.26 darwin), and reword typeparam/mdempsky/16 - the panic value now implements runtime.Error; the message still lacks the source interface type and prints the command-line-arguments package path.
cpunion
added a commit
to cpunion/llgo
that referenced
this pull request
Jul 9, 2026
Re-expresses xgo-dev#1918 on the xgo-dev#2023 base (its remaining ~11k diff lines were the pre-xgo-dev#2012 funcinfo draft, superseded by the stage-5 chain): - recover() only succeeds when called directly by a deferred function (gc semantics): the panic node records the owning Defer frame at rethrow (panicKey/panicNode + GoDeferData), and Recover checks the caller is that frame's direct deferred call. Closure wraps carry StartRecoverFrameAlias/EndRecoverFrame so method-value and closure adapters stay transparent to the ownership check. - Rethrow keeps the xgo-dev#2023 PanicTraceback hook on the unrecovered path. - xfail: retire fixedbugs/issue4066 (2m-timeout entries; now runs in ~2.7s), fixedbugs/issue73916 and issue73916b (go1.26 recover semantics), validated on darwin/arm64 go1.26. Supersedes xgo-dev#1918.
cpunion
added a commit
to cpunion/llgo
that referenced
this pull request
Jul 9, 2026
Re-expresses xgo-dev#1906 on the xgo-dev#2023 base (its remaining ~11k diff lines were the pre-xgo-dev#2012 funcinfo draft, superseded by the stage-5 chain): - cl gains a liveness analysis for stack-allocated objects: allocas whose last use has passed are cleared so bdwgc's conservative stack scan stops keeping dead stack objects (and what they point to) alive; pointer registers are clobbered around the trigger points (llgo_clobber_pointer_regs) and dead stack slots holding the target are zeroed (llgo_clear_stack_ptr, pthread stack-bounds walk). - runtime.SetFinalizer paths (mfinal, runtime_gc, bdwgc binding) hook the cleared-slot machinery so finalizers for dead stack objects run. - xfail: retire deferfin.go, stackobj.go, stackobj3.go, validated on darwin/arm64 go1.24 + go1.26 (stackobj2 already passed). Carries the xgo-dev#2035 shared-GOCACHE commit temporarily (same patch-id, auto-dedups when the chain rebases after xgo-dev#2035 merges). Supersedes xgo-dev#1906.
cpunion
added a commit
to cpunion/llgo
that referenced
this pull request
Jul 16, 2026
Re-expresses xgo-dev#1918 on the xgo-dev#2023 base (its remaining ~11k diff lines were the pre-xgo-dev#2012 funcinfo draft, superseded by the stage-5 chain): - recover() only succeeds when called directly by a deferred function (gc semantics): the panic node records the owning Defer frame at rethrow (panicKey/panicNode + GoDeferData), and Recover checks the caller is that frame's direct deferred call. Closure wraps carry StartRecoverFrameAlias/EndRecoverFrame so method-value and closure adapters stay transparent to the ownership check. - Rethrow keeps the xgo-dev#2023 PanicTraceback hook on the unrecovered path. - xfail: retire fixedbugs/issue4066 (2m-timeout entries; now runs in ~2.7s), fixedbugs/issue73916 and issue73916b (go1.26 recover semantics), validated on darwin/arm64 go1.26. Supersedes xgo-dev#1918.
cpunion
added a commit
to cpunion/llgo
that referenced
this pull request
Jul 17, 2026
Re-expresses xgo-dev#1918 on the xgo-dev#2023 base (its remaining ~11k diff lines were the pre-xgo-dev#2012 funcinfo draft, superseded by the stage-5 chain): - recover() only succeeds when called directly by a deferred function (gc semantics): the panic node records the owning Defer frame at rethrow (panicKey/panicNode + GoDeferData), and Recover checks the caller is that frame's direct deferred call. Closure wraps carry StartRecoverFrameAlias/EndRecoverFrame so method-value and closure adapters stay transparent to the ownership check. - Rethrow keeps the xgo-dev#2023 PanicTraceback hook on the unrecovered path. - xfail: retire fixedbugs/issue4066 (2m-timeout entries; now runs in ~2.7s), fixedbugs/issue73916 and issue73916b (go1.26 recover semantics), validated on darwin/arm64 go1.26. Supersedes xgo-dev#1918.
cpunion
added a commit
to cpunion/llgo
that referenced
this pull request
Jul 17, 2026
…upport Re-expresses the surviving value of xgo-dev#1892 on the xgo-dev#2023 base (its other ~10k lines were an earlier draft of the funcinfo/pclntab machinery, since superseded by xgo-dev#2012/xgo-dev#2016/xgo-dev#2019): - //go:nointerface methods no longer satisfy interfaces: the pragma is recorded at import (cl/import.go -> Program.SetNoInterfaceMethod) and filtered out of abi uncommon method tables; GlobalDCE metadata takes the filtered selection list. Retires the typeparam/mdempsky/15 goroot xfails (validated go1.26 darwin, ci directive mode). - Type-assertion failure between same-named types from different scopes appends '(types from different scopes)' (gc wording). - MatchesClosure unwraps closure types on both sides, fixing assertions between closure and plain function types. - reflect.(*rtype).Method builds the method func value with the closure layout allocation (fixes reflect method-value identity). - xfail: retire fixedbugs/issue16130, fixedbugs/issue29735 (validated go1.24 + go1.26 darwin), and reword typeparam/mdempsky/16 - the panic value now implements runtime.Error; the message still lacks the source interface type and prints the command-line-arguments package path.
cpunion
added a commit
to cpunion/llgo
that referenced
this pull request
Jul 17, 2026
Re-expresses xgo-dev#1906 on the xgo-dev#2023 base (its remaining ~11k diff lines were the pre-xgo-dev#2012 funcinfo draft, superseded by the stage-5 chain): - cl gains a liveness analysis for stack-allocated objects: allocas whose last use has passed are cleared so bdwgc's conservative stack scan stops keeping dead stack objects (and what they point to) alive; pointer registers are clobbered around the trigger points (llgo_clobber_pointer_regs) and dead stack slots holding the target are zeroed (llgo_clear_stack_ptr, pthread stack-bounds walk). - runtime.SetFinalizer paths (mfinal, runtime_gc, bdwgc binding) hook the cleared-slot machinery so finalizers for dead stack objects run. - xfail: retire deferfin.go, stackobj.go, stackobj3.go, validated on darwin/arm64 go1.24 + go1.26 (stackobj2 already passed). Carries the xgo-dev#2035 shared-GOCACHE commit temporarily (same patch-id, auto-dedups when the chain rebases after xgo-dev#2035 merges). Supersedes xgo-dev#1906.
cpunion
added a commit
to cpunion/llgo
that referenced
this pull request
Jul 18, 2026
Re-expresses xgo-dev#1918 on the xgo-dev#2023 base (its remaining ~11k diff lines were the pre-xgo-dev#2012 funcinfo draft, superseded by the stage-5 chain): - recover() only succeeds when called directly by a deferred function (gc semantics): the panic node records the owning Defer frame at rethrow (panicKey/panicNode + GoDeferData), and Recover checks the caller is that frame's direct deferred call. Closure wraps carry StartRecoverFrameAlias/EndRecoverFrame so method-value and closure adapters stay transparent to the ownership check. - Rethrow keeps the xgo-dev#2023 PanicTraceback hook on the unrecovered path. - xfail: retire fixedbugs/issue4066 (2m-timeout entries; now runs in ~2.7s), fixedbugs/issue73916 and issue73916b (go1.26 recover semantics), validated on darwin/arm64 go1.26. Supersedes xgo-dev#1918.
cpunion
added a commit
to cpunion/llgo
that referenced
this pull request
Jul 18, 2026
Re-expresses xgo-dev#1918 on the xgo-dev#2023 base (its remaining ~11k diff lines were the pre-xgo-dev#2012 funcinfo draft, superseded by the stage-5 chain): - recover() only succeeds when called directly by a deferred function (gc semantics): the panic node records the owning Defer frame at rethrow (panicKey/panicNode + GoDeferData), and Recover checks the caller is that frame's direct deferred call. Closure wraps carry StartRecoverFrameAlias/EndRecoverFrame so method-value and closure adapters stay transparent to the ownership check. - Rethrow keeps the xgo-dev#2023 PanicTraceback hook on the unrecovered path. - xfail: retire fixedbugs/issue4066 (2m-timeout entries; now runs in ~2.7s), fixedbugs/issue73916 and issue73916b (go1.26 recover semantics), validated on darwin/arm64 go1.26. Supersedes xgo-dev#1918.
cpunion
added a commit
to cpunion/llgo
that referenced
this pull request
Jul 19, 2026
Re-expresses xgo-dev#1918 on the xgo-dev#2023 base (its remaining ~11k diff lines were the pre-xgo-dev#2012 funcinfo draft, superseded by the stage-5 chain): - recover() only succeeds when called directly by a deferred function (gc semantics): the panic node records the owning Defer frame at rethrow (panicKey/panicNode + GoDeferData), and Recover checks the caller is that frame's direct deferred call. Closure wraps carry StartRecoverFrameAlias/EndRecoverFrame so method-value and closure adapters stay transparent to the ownership check. - Rethrow keeps the xgo-dev#2023 PanicTraceback hook on the unrecovered path. - xfail: retire fixedbugs/issue4066 (2m-timeout entries; now runs in ~2.7s), fixedbugs/issue73916 and issue73916b (go1.26 recover semantics), validated on darwin/arm64 go1.26. Supersedes xgo-dev#1918.
cpunion
added a commit
to cpunion/llgo
that referenced
this pull request
Jul 20, 2026
Re-expresses xgo-dev#1918 on the xgo-dev#2023 base (its remaining ~11k diff lines were the pre-xgo-dev#2012 funcinfo draft, superseded by the stage-5 chain): - recover() only succeeds when called directly by a deferred function (gc semantics): the panic node records the owning Defer frame at rethrow (panicKey/panicNode + GoDeferData), and Recover checks the caller is that frame's direct deferred call. Closure wraps carry StartRecoverFrameAlias/EndRecoverFrame so method-value and closure adapters stay transparent to the ownership check. - Rethrow keeps the xgo-dev#2023 PanicTraceback hook on the unrecovered path. - xfail: retire fixedbugs/issue4066 (2m-timeout entries; now runs in ~2.7s), fixedbugs/issue73916 and issue73916b (go1.26 recover semantics), validated on darwin/arm64 go1.26. Supersedes xgo-dev#1918.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
End-user acceptance for the Stage 5 unwinder (#2019): make the caller info an application developer actually sees correct — panic tracebacks, log/slog locations, testing failure lines — and lock it in with a gc-verified acceptance suite.
What the acceptance run exposed (before this PR)
[0x… main+0x4, SP = 0x24](dladdr, one frame, no file:line)log.Lshortfilemain.go:11:???:1:main.go:11:AddSourcesource=…/main.go:12source=:0source=…/main.go:12t.Errorfunderllgo testx_test.go:6:???:1:x_test.go:6:Fixes
Go-style panic tracebacks: unrecovered panics print
goroutine 1 [running]:plusfunction(...)/ indentedfile:lineper physical frame, via aPanicTracebackhook the public runtime registers with the runtime core; the clite dladdr dump remains the fallback when the FP walk or tables are unavailable. Runtime-internal plumbing frames are filtered by package path (gc hides runtime frames the same way).Uniform caller-frame tracking — no package whitelist: the blanket stdlib exclusion is gone. The existing per-package "transitively reaches runtime.Caller" analysis now applies to stdlib exactly as it always did to third-party code, so
log.Output, slog'sLogger.logand testing's decorate chains keep physical frames and fixed Caller depths count correctly. Packages that never read caller pcs still track nothing and pay nothing.Cross-package call-site anchors: a call into a caller-pc-consuming function of another package (the frame a fixed depth attributes) gets a statement anchor, so
log.Println("x")reports the exact line even though the calling function itself never reads caller pcs. Decided by the same analysis (memoized per package), not by name.Collector: directly-called methods: a type used only concretely never enters
RuntimeTypes, so its methods escaped tracking — exactly howslog.(*Logger).Infolost its frame. Methods are now collected from the package's own type declarations (both receiver forms).gc-conformant naming and format: the main package's display name is normalized to
mainregardless of the module name (frame filters in the wild match on themain.prefix; linker symbols keep the package path), closures display as gc's.funcNinstead of$N, and traceback lines carry gc's+0x<pc-entry>offset (value is codegen-specific, format matches).Program-unique frames pinned:
main.mainand packageinitrun once, so noinline is free — they are the bottom frames of nearly every panic traceback and now report exact statement lines.//go:noinlinefunctions already keep their frames and get statement anchors too.Conformance bar (agreed): format and user-code file:line match gc exactly; runtime-internal, patched-stdlib and startup frames may differ (different runtime, accepted).
Cost: hello-world grows 368 bytes (the traceback printer); no IR golden changed;
plain.*code paths are untouched.Acceptance suite (
test/go/caller_acceptance_test.go)Four probes, every expectation verified against gc: panic traceback contents;
log.Lshortfile+ slogAddSource(text and JSON handlers, package functions and logger methods); a failingt.Errorfunderllgo test; and an introspection grab-bag — goroutine/init/defer callers,FuncForPCnames for value/pointer methods, closures and generic instantiations, and the errors-with-stack capture idiom (zap/sentry style).Documented divergences observed while writing the suite:
.funcNform (linker symbols keep$N); the suite accepts both forms for robustness.FuncForPCreports the surviving symbol (gc does not fold); probes use distinct bodies.main.main,init),//go:noinlinefunctions, and every attributed frame in the log/slog/testing/Caller scenarios are exact.Manual playground (
test/_manualtest/, committed)Five directories runnable with both
goandllgofor side-by-side comparison:panic/(traceback shape),logging/(log/slog locations),callers/(Caller ladder, frames, FuncForPC names, errors-with-stack),testfail/(llgo testfailure lines),cexcept/(hardware faults in C called from Go — segv recovery verified on darwin/arm64 + linux/arm64/amd64; known gaps recorded in its README: fault-site stack needs the panic-snapshot follow-up, SIGFPE/SIGBUS handlers and sigaltstack not installed yet). Every scenario also has atest/goregression: the acceptance tests above plusTestCallerAcceptanceModuleMainNaming(module-named main package must still reportmain.*) andTestCallerAcceptanceCFaultRecover(C NULL-store converts to a recoverable Go panic).Validation (both platforms, before every push)
cl(725s),ssa,internal/build,test/goall ok;gentestsproduced no golden diffs._demo/godemo passes plain and an LTO (-lto=full -globaldce) subset — including the reflect demos whose ELF pcline sections dangled in the first CI round (anchors in inlinable functions; fixed by making frame-keeping a tracking criterion rather than a per-call exception).+0x30= return address − function entry for the probe).Based on #2019 (contains #2012 and #2016); rebases as those merge.
🤖 Generated with Claude Code